/*
 * @Descripttion : 
 * @Autor        : Lilong
 * @Date         : 2022-09-08 00:41:45
 * @LastEditTime : 2022-09-08 00:51:18
 * @FilePath     : \src\hooks\fetch.js
 */
import { ref, isRef, unref, watchEffect } from 'vue'

//异步状态
//每次url变化时(允许接收 ref 作为参数)，都重新请求
export function useFetch(url) {
  const data = ref(null)
  const error = ref(null)

  function doFetch() {
    // 在请求之前重设状态...
    data.value = null
    error.value = null
    // unref() 解包可能为 ref 的值，url是一个ref时，unref(url)的.value会被返回。否则会被原样返回
    fetch(unref(url))
      .then((res) => res.json())
      .then((json) => (data.value = json))
      .catch((err) => (error.value = err))
  }

  if (isRef(url)) {
    // 若输入的 URL 是一个 ref，那么启动一个响应式的请求
    watchEffect(doFetch) //会使用 watchEffect() 启动一个响应式的 effect。该 effect 会立刻执行一次，并在此过程中将 URL 的 ref 作为依赖进行跟踪
  } else {
    // 否则只请求一次
    // 避免监听器的额外开销
    doFetch()
  }

  //推荐返回的是一个包含多个ref的普通的非响应式对象，那么该对象在组件中被解构为ref后还保持响应性，因此对象中每个都用ref，而不用reactive
  //reactive包裹一个对象返回，外面解构后会丢失与hooks内状态的响应性
  //如果更希望以对象属性的形式在组件中来使用组合式函数中返回的状态，应将返回的对象用reactive()包装依次，再点内部属性，如const mouse = reactive(useMouse()); console.log(mouse.x)
  return { data, error }
}
